package top.wshape1.rpc.provider.handler;

import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import top.wshape1.rpc.common.constant.RpcMessageCodeEnum;
import top.wshape1.rpc.common.exception.RpcException;
import top.wshape1.rpc.filter.FilterChain;
import top.wshape1.rpc.filter.FilterChainFactory;
import top.wshape1.rpc.message.RpcRequest;
import top.wshape1.rpc.message.RpcResponse;
import top.wshape1.rpc.provider.service.RpcServiceFactory;

import java.lang.reflect.Method;

/**
 * @author Wshape1
 * @version 1.0
 * @description 接收消费者发送的调用消息的处理器
 * @since 2024-02-02
 */

@Slf4j
@ChannelHandler.Sharable
public class RpcRequestHandler extends SimpleChannelInboundHandler<RpcRequest> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, RpcRequest msg) throws Exception {

        // 接收Req过滤器链
        FilterChain filterChain = FilterChainFactory.getProviderRecReqFilterChain();
        try {
            if (!filterChain.doFilter(msg)) {
                log.debug("The doFilter for receiving the request returns false. msg: {}", msg);
                return;
            }
        } finally {
            filterChain.clearLocal();
        }

        log.debug("接收到调用消息，调用方法{}.{}()，消息内容：{}", msg.getClassName(), msg.getMethodName(), msg);

        RpcResponse rpcResponse = new RpcResponse();
        rpcResponse.setSequenceId(msg.getSequenceId());

        try {

            Class<?> clazz = Class.forName(msg.getClassName());

            Method method = clazz.getMethod(msg.getMethodName(), msg.getParamTypes());

            // 获取本端 已经注册的服务接口
            Object service = RpcServiceFactory.getService(clazz);

            if (service == null)
                throw new RpcException(RpcMessageCodeEnum.RPC_METHOD_NOT_FOUND);

            // 调用方法
            Object result = method.invoke(service, msg.getArgs());

            // setResult方法包括设置resultType和result
            rpcResponse.setResult(result);
            rpcResponse.setCodeAndMsg(RpcMessageCodeEnum.RPC_OK);
        } catch (Exception e) {
            log.debug("调用方法异常{}.{}()，异常信息：{}", msg.getClassName(), msg.getMethodName(), e.getMessage());
            rpcResponse.setException(e);
            // TODO 可以更加明确的设置错误码
            rpcResponse.setCode(RpcMessageCodeEnum.RPC_ERROR.getCode());
            rpcResponse.setMsg(e.getMessage());
        }

        // 发送Resp过滤器链
        FilterChain respFilterChain = FilterChainFactory.getProviderSendRespFilterChain();
        try {
            if (!respFilterChain.doFilter(rpcResponse)) {
                log.debug("The doFilter for sending the response returns false. msg: {}", rpcResponse);
                return;
            }
        } finally {
            respFilterChain.clearLocal();
        }
        ctx.writeAndFlush(rpcResponse);

    }
}
